package com.boarsoft.boar.soagov.svc.biz;

import java.util.List;

import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.common.Constants;
import com.boarsoft.boar.dir.DirBiz;
import com.boarsoft.boar.entity.AppInfo;
import com.boarsoft.boar.entity.DirInfo;
import com.boarsoft.boar.entity.SoaNexus;
import com.boarsoft.boar.soagov.com.ComBiz;
import com.boarsoft.boar.soagov.entity.ComInfo;
import com.boarsoft.boar.soagov.entity.ObjFaces;
import com.boarsoft.boar.soagov.entity.SvcInfo;
import com.boarsoft.boar.soagov.face.ObjFacesBiz;
import com.boarsoft.boar.soagov.nexus.NexusBiz;
import com.boarsoft.boar.soagov.svc.SvcAppBiz;
import com.boarsoft.boar.soagov.svc.SvcBiz;
import com.boarsoft.boar.soagov.svc.SvcLibBiz;
import com.boarsoft.common.Util;
import com.boarsoft.common.dao.PagedResult;
import com.boarsoft.hibernate.biz.SimpleBizImpl;

@Component("svcBiz")
public class SvcBizImpl extends SimpleBizImpl implements SvcBiz {
	@Autowired
	private DirBiz dirBiz;
	@Autowired
	private ComBiz comBiz;
	@Autowired
	private SvcAppBiz svcAppBiz;
	@Autowired
	private SvcLibBiz svcLibBiz;
	@Autowired
	private ObjFacesBiz objFacesBiz;
	@Autowired
	private NexusBiz nexusBiz;

	@Override
	@Transactional
	public ReplyInfo<String> delete(String id) {
		// TODO ? 先删除与之对应的组件，删除组件时会检查组件是否被依赖，并删除树节点和依赖关系
		ReplyInfo<String> ri = comBiz.delete(id);
		svcAppBiz.delete(id);
		dao.delete(SvcInfo.class, id);
		return ri;
	}

	@Override
	@Transactional
	public boolean status(String id, short status) {
		SvcInfo o = dao.get(SvcInfo.class, id);
		if (status == 1) {
			o.setStatus(SvcInfo.STATUS_NOUSE);
		} else {
			o.setStatus(SvcInfo.STATUS_INUSE);
		}
		dao.update(o);
		return true;
	}

	@Override
	@Transactional
	public ReplyInfo<Object> add(DirInfo d, SvcInfo s, ComInfo c) {
		// 需保证svc的code在父级（App）中是唯一的
		StringBuilder sb = new StringBuilder();
		sb.append("and code='").append(s.getCode());
		sb.append("' and parentId='").append(d.getParentId()).append("'");
		if (dao.find(DirInfo.class, sb.toString()) != null) {
			return new ReplyInfo<Object>(Constants.ERROR_DUPLICATED);
		}
		// 1、保存DirInfo
		ReplyInfo<Object> ri = dirBiz.add(d);
		if (!ri.isSuccess()) {
			return ri;
		}
		// 2、保存SvcInfo
		String svcId = d.getId();
		log.info("Save DirInfo {}", svcId);
		s.setId(svcId);
		dao.save(s);
		// 3、再保存App/Lib与Svc的关系
		// parentId可能是appId也可能是libId
		String parentId = d.getParentId();
		DirInfo parent = dirBiz.get(parentId);
		if (parent.getType() == DirInfo.TYPE_APP) {
			svcAppBiz.add(parentId, new String[] { svcId });
		} else {
			svcLibBiz.add(parentId, new String[] { svcId });
		}
		// 4、保存与之对应的subflow组件
		c.setId(svcId);
		dao.save(c);
		// 组件与其它服务和组件的关系在保存FLOW时会做解析和保存。
		return new ReplyInfo<Object>(true, d);
	}

	@Override
	@Transactional
	public ReplyInfo<Object> update(DirInfo d, SvcInfo f, ComInfo c) {
		dirBiz.update(d);
		dao.merge(f);
		dao.merge(c);
		return new ReplyInfo<Object>(true, d);
	}

	@Override
	@Transactional(readOnly = true)
	public SvcInfo get(String id) {
		return (SvcInfo) dao.get(SvcInfo.class, id);
	}

	@Override
	@Transactional(readOnly = true)
	public PagedResult<SvcInfo> list(String projId, String catalog, String key, String orderBy, int pageNo, int pageSize) {
		StringBuilder sb = new StringBuilder();
		sb.append(" from ").append(AppInfo.class.getName());
		sb.append(" a join a.svcs s where 1=1");
		if (Util.strIsNotEmpty(projId)) {
			sb.append(" and a.projId = '").append(projId).append("'");
		}
		if (Util.strIsNotEmpty(catalog)) {
			sb.append(" and s.catalog = '").append(catalog).append("'");
		}
		if (Util.strIsNotEmpty(key)) {
			sb.append(" and (s.code like '%").append(key);
			sb.append("%' or s.name like '%").append(key);
			sb.append("%')");
		}
		int total = dao.getTotal("select count(s.id)".concat(sb.toString()));
		// if (Util.strIsNotEmpty(orderBy)) {
		// sb.append(" order by ").append(orderBy);
		// } else {
		// sb.append(" order by name");
		// }
		List<SvcInfo> lt = dao.list("select s".concat(sb.toString()), pageNo, pageSize);
		return new PagedResult<SvcInfo>(total, lt, pageNo, pageSize);
	}

	@Override
	@Transactional
	public String copy(String sourceId, String parentId, String newId) {
		// copy SvcInfo
		SvcInfo n = this.get(sourceId);
		dao.evict(n);
		n.setId(newId);
		dao.save(n);
		// copy ObjFaces，复制“我”依赖的接口
		List<ObjFaces> ofLt = objFacesBiz.list(sourceId);
		for (ObjFaces of : ofLt) {
			if (of.getFace() == null) {
				log.warn("Wrong object-face relation between object {}/{} and face {}", of.getObjType(), of.getObjId(),
						of.getFaceId());
				continue;
			}
			dao.evict(of);
			of.setId(null);
			of.setObjId(n.getId());
			dao.save(of);
		}
		// copy SoaNexus，只复制“我的依赖”，不复制“依赖我的”
		List<SoaNexus> snLt = nexusBiz.listByMe(sourceId);
		for (SoaNexus sn : snLt) {
			dao.evict(sn);
			sn.setId(null);
			sn.setObjId0(n.getId());
			dao.save(sn);
		}
		return n.getId();
	}

	@Override
	@Transactional
	public boolean move(String id, String to) {
		return true;
	}

	@Override
	@Transactional
	public void save(SvcInfo o) {
		if (Util.strIsEmpty(o.getId())) {
			dao.save(o);
		} else {
			dao.merge(o);
		}
	}

	@Override
	@Transactional(readOnly = true)
	public SvcInfo find(String group, String name, String faceId, String version) {
		Query<SvcInfo> q = dao.createQuery(//
				"and catalog=:group and code=:name and faceId=:faceId and version=:version", SvcInfo.class);
		q.setParameter("group", group);
		q.setParameter("name", name);
		q.setParameter("faceId", faceId);
		q.setParameter("version", version);
		return q.uniqueResult();
	}
}